package main

import "fmt"

type Any interface{}

type Exam struct {
	Name   string
	Course string
	Score  int
}

type Exams []*Exam

func (e Exams) Process(f func(ex *Exam)) {
	for _, exam := range e {
		f(exam)
	}
}

func (E Exams) FindAll(fn func(ex *Exam) bool) Exams {
	res := make([]*Exam, 0)
	for _, exam := range E {
		if fn(exam) {
			res = append(res, exam)
		}
	}
	return res
}

func (E Exams) Map(fn func(ex *Exam) Any) []Any {
	res := make([]Any, len(E))
	ix := 0
	E.Process(func(e *Exam) {
		res[ix] = fn(e)
		ix++
	})
	return res
}

func MakeSortedAppender(courses []string) (func(e *Exam), map[string]Exams) {
	sortedExams := make(map[string]Exams)
	for _, course := range courses {
		sortedExams[course] = make([]*Exam, 0)
	}
	sortedExams["Default"] = make([]*Exam, 0)
	appender := func(e *Exam) {
		if _, ok := sortedExams[e.Course]; ok {
			sortedExams[e.Course] = append(sortedExams[e.Course], e)
		} else {
			sortedExams["Default"] = append(sortedExams["Default"], e)
		}
	}

	return appender, sortedExams
}

func main() {
	exam1 := &Exam{"Zhongli", "talk", 90}
	exam2 := &Exam{"Zhongli", "power", 90}
	exam3 := &Exam{"Gongzi", "talk", 60}
	exam4 := &Exam{"Gongzi", "power", 60}
	exam5 := &Exam{"Hutao", "talk", 60}
	exam6 := &Exam{"Hutao", "power", 90}
	allExams := Exams{exam1, exam2, exam3, exam4, exam5, exam6}
	talkHightScore := allExams.FindAll(func(e *Exam) bool {
		return e.Course == "talk" && e.Score >= 90
	})
	fmt.Println(talkHightScore)
	courses := []string{"talk", "power", "weapon"}
	appender, sortedExams := MakeSortedAppender(courses)
	allExams.Process(appender)
	fmt.Println(sortedExams)
}
